package _go

import "math"

/*
319. 灯泡开关
难度
中等

281

收藏

分享
切换为英文
接收动态
反馈
初始时有 n 个灯泡处于关闭状态。第一轮，你将会打开所有灯泡。接下来的第二轮，你将会每两个灯泡关闭一个。

第三轮，你每三个灯泡就切换一个灯泡的开关（即，打开变关闭，关闭变打开）。第 i 轮，你每 i 个灯泡就切换一个灯泡的开关。直到第 n 轮，你只需要切换最后一个灯泡的开关。

找出并返回 n 轮后有多少个亮着的灯泡。



示例 1：



输入：n = 3
输出：1
解释：
初始时, 灯泡状态 [关闭, 关闭, 关闭].
第一轮后, 灯泡状态 [开启, 开启, 开启].
第二轮后, 灯泡状态 [开启, 关闭, 开启].
第三轮后, 灯泡状态 [开启, 关闭, 关闭].

你应该返回 1，因为只有一个灯泡还亮着。
示例 2：

输入：n = 0
输出：0
示例 3：

输入：n = 1
输出：1


提示：

0 <= n <= 109
通过次数44,860提交次数79,245*/
//官方答案  我是没有总结出来这个规律 其实就是一个平方根的过程
//要注意的是+0.5的意思是为了避免精度问题 + 0.05也是可以的
//浮点数存储问题。根号4.0可能算出来是1.999999（打个比方）
func bulbSwitch(n int) int {
	return int(math.Sqrt(float64(n) + 0.5))
}

//模拟法 会超时 不过可以解出来
func bulbSwitch(n int) int {
	//定义一个n+1个数组
	l := make([]bool, n+1)

	//要循环的轮次
	for lun := 1; lun < n+1; lun++ {
		//每个轮次内要执行的交换
		for i := 1; i*lun < n+1; i++ {
			//lun次就是不仅长度 也可用加法做 i += lun
			if l[i*lun] {
				l[i*lun] = false
			} else {
				l[i*lun] = true
			}

		}
	}
	//fmt.Printf(" %+v \n",l)

	res := 0
	//计算一下剩下的亮的个数
	for _, v := range l {
		if v {
			res++
		}
	}
	return res
}
